package com.esig.socket;

import javax.swing.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

public class ServerUI2 extends JFrame {
    MainServer server;

    public void setServer(MainServer server) {
        this.server = server;
    }

    public static void main(String[] args) {
        MainServer server2 = new MainServer();
    }

}

class MainServer {
    Socket[] threads;
    ThreadServer1[] client = new ThreadServer1[60];
    ServerSocket soc;
    int count;

    //初始化ServerSocket服务端
    public MainServer() {
        threads = new Socket[60];   //设置最大的用户连接数为60
        try {
            soc = new ServerSocket(6666);  //新建服务器端的ServerSocket
            System.out.println("连接socke成功，当前IP：" + InetAddress.getLocalHost().getHostAddress()); //但是这个ip好像不是无限网络的ip，是以太网的ip
        } catch (Exception e) {
            System.out.println(e);
        }
        count = 0;

        accept();
    }

    public void sendAll(String msg) {
        for (int i = 0; i < 60; i++) sendMsg(msg, i);   //发送所有居然只是循环而已？
    }

    public boolean sendMsg(String msg, int i) {
        if (client[i] != null) {
            client[i].sendMsg(msg); //这个sendMsg()不是方法本身，而是最下面的发送消息的方法,返回boolean值呢，其实没什么必要,只是给开发者一个提示
            return true;
        } else {
            return false;
        }
    }

    // 查找空下标，然后accept接收的时候放进空下标里面
    int searchIndex() {
        for (int i = 0; i < 60; i++)
            if (client[i] == null) return i;
        return -1;
    }

    public void accept() {
        try {
            while (true) {
                int i = searchIndex();  //查找空的下标，没有则（不断循环，等待新的空位出来） 跳过下面的程序
                if (i == -1) continue;
                threads[i] = soc.accept();//????????????? 这里很骚，这里不是调用方法本身，而是调用socket自带的方法生成socket ctrl鼠标左键看看
                client[i] = new ThreadServer1(this, threads[i], i);

                System.out.println("当前用户数：" + (++count));
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

//可以和一个用户交互
class ThreadServer1 extends Thread {
    int port;
    Socket client;
    BufferedReader in;
    PrintWriter out;
    int index;
    MainServer server;

    public ThreadServer1(MainServer server, Socket client, int index) {
        this.server = server;
        this.client = client;
        this.index = index;
        this.port = port;   //?????????????????????  后期可以设置端口号，现在没设置所以提示为0
        try {
            System.out.println("启动服务器成功，等待端口号:" + port);
            System.out.println("连接成功！来自" + client.toString());
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            /**
             * 先实例化BufferedReader缓存流，再实例化InputStreamReader输入流，为了后续能通过readLine()方法一行一行的读数据
             * client.getInputStream() 是获取客户端socket的输入流
             */
            out = new PrintWriter(client.getOutputStream(), true);
            /**
             * 实例化PrintWrite类 实现通过println()输出任意类型的数据
             * 可能对于游戏来说不太好，因为毕竟tcp协议传字节(byte)为主，他封装了一层，可能占用的空间增大很多
             * 但是也有好处，解决了拆包、粘包问题，就是不会字节没获取完就执行方法，因为读是通过in.readLine()一行一行的读的
             * 不过本身，拆包、粘包问题就不会很难解决，因为int、long等非字符串的字节数是固定的，加上条件判断即可
             * client.getOutputStream() 是获取客户端socket的输出流
             * autoFlush 默认自动确认输出，flush是是否输出
             */
        } catch (Exception e) {
            System.out.println(e);
        }
        this.start();
        /**
         *  启动线程，这里的线程很骚！ 下面明明是while(true) 但是他没有一直循环而是别人一发信息才执行，
         *  你可以试着在while(true) 下面sout一个1，测试一下，然后我发现这里的run好像是，被socket重写了，
         *  我一开始还以为，开socket就是开个线程，然后不断的判断有没有值，但是好像不是的，socket本身自带长连接
         *  这个 while(true) 我理解的就是 socket通过 线程通信(wait notify) ，实现有人发消息就唤醒线程，接收完毕后，就让线程等待
         */

    }

    public void run() {

        String msg = "";
        while (true) {  //????????开启线程后并不会一直执行，而是别人一发消息就执行
            try {
                msg = in.readLine();
            } catch (SocketException e) {
                System.out.println(e);
                server.client[index] = null;
                break;
            } catch (Exception e) {
                System.out.println(e);
            }
            if (msg != null && msg.trim() != "") {
                System.out.println( (index + 1) + "," + msg);
                server.sendAll( (index + 1) + "," + msg);  //发送给所有客户端
            }
        }
    }

    public void sendMsg(String msg) {
        try {
            out.println(msg); //通过PrintWriter类的println()输出信息，然后通过socket线程判断，是否有新增输出信息，后渲染到UI
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}


